package com.example.adms.attendance.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.adms.attendance.dto.*;
import com.example.adms.attendance.entity.AllAttDB;
import com.example.adms.attendance.entity.Attendance;
import com.example.adms.attendance.mapper.AttendanceMapper;
import com.example.adms.attendance.service.AttendanceService;
import com.example.adms.attendance.vo.*;
import com.example.adms.depart.entity.Depart;
import com.example.adms.depart.service.DepartService;
import com.example.adms.vo.Result;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AttendanceServiceImpl extends ServiceImpl<AttendanceMapper, Attendance> implements AttendanceService {

    @Autowired
    private DepartService departService;

    @Autowired
    private AttendanceMapper attendanceMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 签到处理
     * @param onParams
     * @return
     */
    @Override
    public Result onHandle(OnParams onParams) {
        Depart depart = departService.getDepartByUserId(onParams.getUserId());
        LocalTime workOnTime = depart.getWorkonTime();//部门上班时间
        //签到时间
        LocalDateTime onTimeWithDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(onParams.getOnTime()), ZoneOffset.ofHours(8));
        LocalTime onTime = LocalTime.of(onTimeWithDate.getHour(), onTimeWithDate.getMinute());
        //签到时间和部门上班时间对比，迟到返回1
        int isLate = onTime.compareTo(workOnTime);
        //用户签到后先查redis中有无数据，有数据说明今天已经签到，无数据说明今天还没有签到
        String s = redisTemplate.opsForValue().get("OnTime_" + onParams.getUserId());
        if (ObjectUtils.isEmpty(s)){
            //无数据说明今天没有签到,将参数保存到redis，过期时间1天
            redisTemplate.opsForValue().set("OnTime_"+onParams.getUserId(), JSONObject.toJSONString(onParams),1, TimeUnit.DAYS);
            Attendance attendance = new Attendance();
            attendance.setUserId(onParams.getUserId());
            attendance.setOnTime(onParams.getOnTime());
            if (isLate == 1){
                attendance.setIsLate(1);
            }
            boolean saveFlag = this.save(attendance);
            if (saveFlag){
                return Result.success(null);
            } else {
                redisTemplate.delete("OnTime_"+onParams.getUserId());
                return Result.fail(500,"签到失败");
            }
        } else {
            //有数据说明今天已经签到过
            return Result.fail(500,"今天已经签到过了");
        }
    }

    /**
     * 签退处理
     * @param offParams
     * @return
     */
    @Override
    public Result offHandle(OffParams offParams) {
        Depart depart = departService.getDepartByUserId(offParams.getUserId());
        LocalTime workOffTime = depart.getWorkoffTime();
        //签退时间
        LocalDateTime offTimeWithDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(offParams.getOffTime()), ZoneOffset.ofHours(8));
        LocalTime offTime = LocalTime.of(offTimeWithDate.getHour(), offTimeWithDate.getMinute());
        //签退时间和部门下班时间对比，早退返回-1
        int isEarly = offTime.compareTo(workOffTime);
        //用户签退后先查redis中有无数据，有数据说明今天已经签退，无数据说明今天还没有签退
        String s = redisTemplate.opsForValue().get("OffTime_" + offParams.getUserId());
        if (ObjectUtils.isEmpty(s)){
            //无数据说明今天没有签到,将参数保存到redis，过期时间1天
            redisTemplate.opsForValue().set("OffTime_"+offParams.getUserId(), JSONObject.toJSONString(offParams),1, TimeUnit.DAYS);
            //获取redis中签到时存的对象，获取出来作为签到更新记录的唯一标识
            String onTimeStr = redisTemplate.opsForValue().get("OnTime_" + offParams.getUserId());
            OnParams onParams = JSONObject.parseObject(onTimeStr, OnParams.class);

            LambdaQueryWrapper<Attendance> queryWrapper = new LambdaQueryWrapper<>();
            Attendance attendance = new Attendance();
            attendance.setOffTime(offParams.getOffTime());
            if (isEarly == -1){
                attendance.setIsEarly(1);
            }
            //通过用户当天的签到时间作为唯一标识进行更新
            queryWrapper.eq(Attendance::getOnTime,onParams.getOnTime());
            boolean updateFlag = this.update(attendance,queryWrapper);

            if (updateFlag){
                return Result.success(null);
            } else {
                redisTemplate.delete("OffTime_"+offParams.getUserId());
                return Result.fail(500,"签退失败");
            }
        } else {
            //有数据说明今天已经签退过
            return Result.fail(500,"今天已经签退过了");
        }
    }

    /**
     * 个人考勤信息查询
     * @param oneAttQueryParams
     * @return
     */
    @Override
    public Result getAttendanceForOne(OneAttQueryParams oneAttQueryParams) {
        LambdaQueryWrapper<Attendance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Attendance::getOnTime, oneAttQueryParams.getStartTime());
        queryWrapper.le(Attendance::getOnTime,oneAttQueryParams.getEndTime());
        queryWrapper.eq(Attendance::getUserId,oneAttQueryParams.getUserId());

        List<Attendance> attendanceList = this.list(queryWrapper);
        List<OneAttVo> resList = new ArrayList<>();
        for (Attendance attendance : attendanceList){
            OneAttVo oneAttVo = new OneAttVo();
            BeanUtils.copyProperties(attendance,oneAttVo);

            //获取当天日期
            LocalDate date = Instant.ofEpochMilli(attendance.getOnTime()).atZone(ZoneOffset.ofHours(8)).toLocalDate();
            DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String dateStr = date.format(df1);


            DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            //获取当天签到时间
            LocalDateTime onTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(attendance.getOnTime()),ZoneOffset.ofHours(8));
            String onTimeStr = onTime.format(df2);
            //获取当天签退时间
            LocalDateTime offTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(attendance.getOffTime()),ZoneOffset.ofHours(8));
            String offTimeStr = offTime.format(df2);

            oneAttVo.setDate(dateStr);
            oneAttVo.setOnTimeDay(onTimeStr);
            oneAttVo.setOffTimeDay(offTimeStr);

            resList.add(oneAttVo);
        }
        return Result.success(resList);
    }

    /**
     * 所有人考勤信息查询
     * @param allAttQueryParams
     * @return
     */
    @Override
    public Result getAttendanceForAll(AllAttQueryParams allAttQueryParams) {
        Map<String,Object> map = new HashMap<>();
        map.put("departId",allAttQueryParams.getDepartId());
        map.put("name",allAttQueryParams.getName());
        map.put("startTime",allAttQueryParams.getStartTime());
        map.put("endTime",allAttQueryParams.getEndTime());
        List<AllAttDB> list = attendanceMapper.selectAttendanceByConditionForAll(map);

        List<AllAttVo> resList = new ArrayList<>();
        for (AllAttDB db : list){
            AllAttVo allAttVo = new AllAttVo();
            BeanUtils.copyProperties(db,allAttVo);

            //获取当天日期
            LocalDate date = Instant.ofEpochMilli(db.getOnTime()).atZone(ZoneOffset.ofHours(8)).toLocalDate();
            DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String dateStr = date.format(df1);

            DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            //获取当天签到时间
            LocalDateTime onTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(db.getOnTime()),ZoneOffset.ofHours(8));
            String onTimeStr = onTime.format(df2);
            //获取当天签退时间
            LocalDateTime offTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(db.getOffTime()),ZoneOffset.ofHours(8));
            String offTimeStr = offTime.format(df2);

            allAttVo.setDate(dateStr);
            allAttVo.setOnTimeDay(onTimeStr);
            allAttVo.setOffTimeDay(offTimeStr);

            resList.add(allAttVo);
        }
        return Result.success(resList);
    }

    /**
     * 统计某月各部门迟到早退情况
     * @param month
     * @return
     */
    @Override
    public Result getTotalAttendance(Integer month) {
        Map<String,Object> map = new HashMap<>();
        map.put("month",month);
        List<DepartLateAndEarlyVo> lateList = attendanceMapper.selectCountLateByDepart(map);
        List<DepartLateAndEarlyVo> earlyList = attendanceMapper.selectCountEarlyByDepart(map);
        List<DepartLateAndEarlyVo> resList = null;
        //根据list长度进行不同处理
        if (lateList.size() >= earlyList.size()){
            for (DepartLateAndEarlyVo late : lateList){
                for(DepartLateAndEarlyVo early : earlyList){
                    if (early.getDepartId().equals(late.getDepartId())){
                        BeanUtils.copyProperties(early,late,"lateNums");
                    } else {
                        late.setEarlyNums(0);
                    }
                }
            }
            resList = lateList;
        } else {
            for(DepartLateAndEarlyVo early : earlyList){
                for(DepartLateAndEarlyVo late : lateList){
                    if (late.getDepartId().equals(early.getDepartId())){
                        BeanUtils.copyProperties(late,early,"earlyNums");
                    } else {
                        early.setLateNums(0);
                    }
                }
            }
            resList = earlyList;
        }

        
        Map<String,Object> resMap = new HashMap<>();
        resMap.put("list",resList);

        return Result.success(resList);
    }

    /**
     * 获取每月迟到最多的员工
     * @param month
     * @return
     */
    @Override
    public Result getMostLate(Integer month) {
        Map<String,Object> map = new HashMap<>();
        map.put("month",month);
        MostLateUser mostLateUser = attendanceMapper.selectMostLateUser(map);
        return Result.success(mostLateUser);
    }

    /**
     * 获取每月早退最多的员工
     * @param month
     * @return
     */
    @Override
    public Result getMostEarly(Integer month) {
        Map<String,Object> map = new HashMap<>();
        map.put("month",month);
        MostEarlyUser mostEarlyUser = attendanceMapper.selectMostEarlyUser(map);
        return Result.success(mostEarlyUser);
    }
}
